<?php

namespace app\common\service\learn;

use app\common\enums\AccountTypeEnum;
use app\common\enums\AntiForgettingFlagEnum;
use app\common\enums\LearnMeansEnum;
use app\common\enums\MemorizeModeEnum;
use app\common\model\banxi\course\Lexicon;
use app\common\model\banxi\learn\LearnSkRecord;
use app\common\model\banxi\learn\LearnSkWordRecord;
use app\common\model\banxi\learn\LearnWordMemorizeRecord;
use app\common\service\ApiService;
use ba\Exception;
use think\db\exception\PDOException;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Log;

class LearnWordMemorizeService extends ApiService
{

    /**
     * 获取统计数据
     * @param int|null $trainerId 教练ID
     * @param int|null $studentId 学员ID
     * @param string $learnMeans 学习方式
     * @param int $courseId 课程ID
     * @return array 统计数据
     */
    public function getTjData($trainerId, $studentId, $learnMeans, $courseId)
    {
        // 设置记忆模式为识记模式
        $memorizeMode = MemorizeModeEnum::E1; // MemorizeMode.E1 对应值

        $accountInfo = $this->AccountInfo($trainerId, $studentId, $learnMeans);
        $accountId = $accountInfo['accountId'];
        $accountType = $accountInfo['accountType'];

        // 基础查询条件
        $LearnWordMemorizeRecordModel = new LearnWordMemorizeRecord();
        $baseQuery = $LearnWordMemorizeRecordModel
            ->alias('r')
            ->join('banxi_lexicon l',
                'l.courseId = r.courseId AND l.word = r.word')
            ->where('r.accountId', $accountId)
            ->where('r.accountType', $accountType)
            ->where('r.memorizeMode', $memorizeMode)
            ->where('r.courseId', $courseId)
            ->where('r.learnMeans', $learnMeans);

        // 今日待复习
        $todayReviewNum = clone $baseQuery;
        $todayReviewNum = $todayReviewNum->where(function ($query) {
            $query->where('r.reviewTime', '<', date('Y-m-d'))
                ->whereOr('r.reviewTime', 'null');
        })
            ->where('r.memorizeLevel', 'between', [0, 6])
            ->count();

        // 今日识词
        $todayMemorizeNum = clone $baseQuery;
        $todayMemorizeNum = $todayMemorizeNum->where(function ($query) {
            $query->where('r.newTime', 'like', date('Y-m-d') . '%')
                ->whereOr('r.reviewTime', 'like', date('Y-m-d') . '%');
        })
            ->where('r.memorizeLevel', 'between', [1, 7])
            ->count();

        // 累计识词
        $totalMemorizeNum = clone $baseQuery;
        $totalMemorizeNum = $totalMemorizeNum->where('r.memorizeLevel', 7)
            ->count();

        // 构造返回结果
        $tjData = [
            'todayMemorizeNum' => $todayMemorizeNum,
            'todayReviewNum' => $todayReviewNum,
            'totalMemorizeNum' => $totalMemorizeNum
        ];

        return $tjData;
    }

    /**
     * 获取记忆等级数量
     * @param int|null $trainerId 教练ID
     * @param int|null $studentId 学员ID
     * @param string $learnMeans 学习方式
     * @param int $courseId 课程ID
     * @return array 记忆等级数量列表
     */
    public function getMemorizeLevelNum($trainerId, $studentId, $learnMeans, $courseId) {
        // 设置记忆模式为识记模式
        $memorizeMode = MemorizeModeEnum::E1; // MemorizeMode.E1 对应值

        // 查询学习记录
        $accountInfo = $this->AccountInfo($trainerId, $studentId, $learnMeans);
        $accountId = $accountInfo['accountId'];
        $accountType = $accountInfo['accountType'];

        // 构造查询条件
        $LearnWordMemorizeRecordModel = new LearnWordMemorizeRecord();
        $rows = $LearnWordMemorizeRecordModel
            ->alias('r')
            ->join('banxi_lexicon l', 'l.courseId = r.courseId AND l.word = r.word')
            ->field(['r.memorizeLevel as level', 'COUNT(*) as count'])
            ->where('r.accountId', $accountId)
            ->where('r.accountType', $accountType)
            ->where('r.memorizeMode', $memorizeMode)
            ->where('r.courseId', $courseId)
            ->where('r.learnMeans', $learnMeans)
            ->group('r.memorizeLevel')
            ->select();


        // 初始化结果列表
        $resultList = array_fill(0, 8, 0);

        // 填充结果
        foreach ($rows as $row) {
            $level = $row['level'];
            if ($level >= 0 && $level < 8) {
                $resultList[$level] = (int)$row['count'];
            }
        }

        return $resultList;
    }

    /**
     * 查询学新单词
     * @param int $page 页码
     * @param int $limit 每页数量
     * @param int|null $trainerId 教练ID
     * @param int|null $studentId 学员ID
     * @param string $learnMeans 学习方式
     * @param int $courseId 课程ID
     * @return array 新单词列表
     */
    public function getNewWord($page, $limit, $trainerId, $studentId, $learnMeans, $courseId) {
        // 设置记忆模式为识记模式
        $memorizeMode = MemorizeModeEnum::E1; // MemorizeMode.E1 对应值

        // 查询学习记录
        $accountInfo = $this->AccountInfo($trainerId, $studentId, $learnMeans);
        $accountId = $accountInfo['accountId'];
        $accountType = $accountInfo['accountType'];

        // 查询待复习单词
        $LearnWordMemorizeRecordModel = new LearnWordMemorizeRecord();
        $learnWordMemorizeRecordList = $LearnWordMemorizeRecordModel->listByCourseAndAccount(
            $accountId,
            $accountType,
            $courseId,
            null,
            null,
            $learnMeans,
            $memorizeMode,
            false
        );

        // 提取单词列表
        $words = [];
        foreach ($learnWordMemorizeRecordList as $record) {
            $words[] = $record['word'];
        }

        // 查询未学过的单词
        $LexiconModel = new Lexicon();
        return $LexiconModel->listByCourseIdAndNotWords($page, $limit, $courseId, $words);
    }


    /**
     * 创建账号信息
     *
     * @param int|null $trainerId  教练ID（如果传了就以教练身份进行操作）
     * @param int|null $studentId  学员ID（如果传了就以学员身份进行操作）
     * @param string $learnMeans 学习方式
     */
    public function AccountInfo($trainerId, $studentId, $learnMeans) {
        $accountId = null;
        $accountType = AccountTypeEnum::TRAINER; // AccountType.TRAINER 对应值

        if (!$studentId) {
            $accountId = strval($studentId);
            $accountType = AccountTypeEnum::STUDENT; // AccountType.STUDENT 对应值
        } else {
            $accountId = strval($trainerId);
        }

        // 如果学习方式是教学模式，则必须提供学员ID
        if ($learnMeans == LearnMeansEnum::E1) { // LearnMeans.E1 对应值
            if (!$studentId) {
                getResponseException('开始上课失败，学员ID不能为空', [], 1, 'ERROR');
            }
        }

        return ['accountId'=>$accountId,'accountType'=>$accountType];
    }

    /**
     * 提交学习识记
     *
     * @param string $accountId 学习人ID
     * @param string $accountType 学习人类型
     * @param array $submitLearn 提交的学习数据
     * @return array
     */
    public function submitLearnRememberWord($accountId, $accountType, $submitLearn)
    {
        Db::startTrans();
        try {
            $appointmentId = isset($submitLearn['appointmentId']) ? $submitLearn['appointmentId'] : null;
            $courseId = $submitLearn['courseId'];
            $memorizeMode = MemorizeModeEnum::E1; // 识记模式
            $learnWordList = $submitLearn['learnWordList'];
            $words = array_column($learnWordList, 'word');

            $learnWordMemorizeRecordList = null;
            $learnMeans = LearnMeansEnum::E2; // 默认为练习
            $LearnWordMemorizeRecordModel = new LearnWordMemorizeRecord();
            if ($appointmentId) {
                $learnMeans = LearnMeansEnum::E1; // 教学模式

                // 获取上课记录
                $LearnSkRecordModel = new LearnSkRecord();
                $learnSkRecord = $LearnSkRecordModel->where('appointmentId', $appointmentId)->find();

                if (!$learnSkRecord) {
                    throw new ValidateException('上课记录不存在');
                }

                if ($learnSkRecord['trainerId'] != $accountId) {
                    throw new ValidateException('上课记录不存在');
                }

                if ($learnSkRecord['isEnd']) {
                    throw new ValidateException('上课记录已结束');
                }
//                halt($learnSkRecord);
                $skId = $learnSkRecord['id'];
                $accountId = (string)$learnSkRecord['studentId'];
//                Log::info('$accountId_1:'.$accountId);
                $accountType = AccountTypeEnum::STUDENT; // 学员

                // 查询学习记录
                $learnWordMemorizeRecordList = $LearnWordMemorizeRecordModel
                    ->where('courseId', $courseId)
                    ->where('accountId', $accountId)
                    ->where('accountType', $accountType)
                    ->where('memorizeMode', $memorizeMode)
                    ->where('learnMeans', $learnMeans)
                    ->whereIn('word', $words)
                    ->select();
//                Log::info('记录上课学习单词记录');
                // 记录上课学习单词记录
                $LearnSkWordRecordModel = new LearnSkWordRecord();
                $LearnSkWordRecordModel->submitLearnWord(
                    $skId,
                    $learnSkRecord['studentId'],
                    $learnSkRecord['studentOrgId'],
                    $learnSkRecord['trainerId'],
                    $courseId,
                    $learnWordList,
                    $learnWordMemorizeRecordList,
                    AntiForgettingFlagEnum::E2, // E2抗遗忘标识
                    false // 识记模式，非学新
                );
//                Log::info('记录实际上课课程ID');
                // 记录实际上课课程ID
                $this->actualSkCourseId($learnSkRecord, $courseId);
            }
            Log::info('$accountId_2:'.$accountId);
            // 查询学习记录
            if (!$learnWordMemorizeRecordList) {
                $learnWordMemorizeRecordList = $LearnWordMemorizeRecordModel
                    ->where('courseId', $courseId)
                    ->where('accountId', $accountId)
                    ->where('accountType', $accountType)
                    ->where('memorizeMode', $memorizeMode)
                    ->where('learnMeans', $learnMeans)
                    ->whereIn('word', $words)
                    ->select();
            }
//            Log::info('$accountId_3:'.$accountId);
//            Log::info('提交学习识记记录'.$accountId);
            // 提交学习识记记录
            $learnResult = $LearnWordMemorizeRecordModel->submitLearnRememberWordRecord(
                $accountId,
                $accountType,
                $learnMeans,
                $memorizeMode,
                $submitLearn,
                $learnWordMemorizeRecordList
            );
//            Log::info('如果是学员自主练习');
            // 如果是学员自主练习，更新自主练习次数
            if ($accountType == AccountTypeEnum::STUDENT && $learnMeans == LearnMeansEnum::E2) {
                $StudentModel = new Student();
                $StudentModel->where('id', $accountId)->setInc('selfPracticeNum', 1);
            }

            Db::commit();
            return $learnResult;
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }

    }



    /**
     * 记录实际上课课程ID
     */
    private function actualSkCourseId($learnSkRecord, $courseId)
    {
        if (!$courseId) {
            return;
        }

        $actualCourseId = "";
        $actualCourseIdList = !empty($learnSkRecord['actualCourseId']) ?
            explode(',', $learnSkRecord['actualCourseId']) : [];

        if (empty($actualCourseIdList)) {
            $actualCourseId = (string)$courseId;
        } else {
            if (!in_array((string)$courseId, $actualCourseIdList)) {
                $actualCourseId = $learnSkRecord['actualCourseId'] . "," . $courseId;
            }
        }

        if ($actualCourseId) {
            LearnSkRecord::where('id', $learnSkRecord['id'])->update(['actualCourseId' => $actualCourseId]);
        }
    }

    /**
     * 获取课程复习单词列表
     *
     * @param int $trainerId 教练ID（如果传了就以教练身份进行操作）
     * @param int $studentId 学员ID（如果传了就以学员身份进行操作）
     * @param int $learnMeans 学习方式
     * @param int $courseId 课程ID
     * @return array 词库列表
     */
    public function getReviewWord($trainerId = null, $studentId = null, $learnMeans = 2, $courseId = null)
    {
        try {
            // 定义识记模式（对应MemorizeMode.E1）
            $memorizeMode = MemorizeModeEnum::E1;

            // 查询学习记录
            $accountId = "";
            $accountType = AccountTypeEnum::TRAINER; // TRAINER

            if ($studentId) {
                $accountId = strval($studentId);
                $accountType = AccountTypeEnum::STUDENT; // STUDENT
            } else {
                $accountId = strval($trainerId);
            }

            // 如果是教学模式，学员ID不能为空
            if ($learnMeans == LearnMeansEnum::E1 && !$studentId) {
                throw new Exception("学员ID不能为空");
            }

            $LearnWordMemorizeRecordModel = new LearnWordMemorizeRecord();
            // 查询学习记录（等级0-6的单词）
            $learnWordMemorizeRecordList = $LearnWordMemorizeRecordModel->listByCourseAndAccount(
                $accountId,
                $accountType,
                $courseId,
                0,
                6,
                $learnMeans,
                $memorizeMode,
                true
            );

            // 提取单词列表
            $words = [];
            foreach ($learnWordMemorizeRecordList as $record) {
                $words[] = $record['word'];
            }

            // 如果没有找到单词，返回空数组
            if (empty($words)) {
                return [];
            }

            // 根据课程ID和单词列表查询词库信息
            $LexiconModel = new Lexicon();
            $lexiconList = $LexiconModel->listByCourseIdAndWords($courseId, $words);

            return $lexiconList;
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
    }
}
